package com.kexio.core.security.jwt;

import com.kexio.core.security.context.UserContext;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * JWT令牌生成器
 *
 * @author Kexio Team
 * @since 1.0.0
 */
public class JwtTokenProvider {

    private static final Logger log = LoggerFactory.getLogger(JwtTokenProvider.class);

    private final JwtService jwtService;

    public JwtTokenProvider(JwtService jwtService) {
        this.jwtService = jwtService;
    }

    /**
     * 为用户生成访问令牌
     *
     * @param userContext 用户上下文
     * @return 访问令牌
     */
    public String generateAccessToken(UserContext userContext) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", userContext.getUserId());
        claims.put("username", userContext.getUsername());
        claims.put("nickname", userContext.getNickname());
        claims.put("tenantId", userContext.getTenantId());
        claims.put("roles", userContext.getRoles());
        claims.put("permissions", userContext.getPermissions());
        claims.put("type", "access");

        String token = jwtService.generateToken(userContext.getUsername(), claims);
        log.debug("为用户 {} 生成访问令牌成功", userContext.getUsername());
        return token;
    }

    /**
     * 为用户生成刷新令牌
     *
     * @param userContext 用户上下文
     * @return 刷新令牌
     */
    public String generateRefreshToken(UserContext userContext) {
        String token = jwtService.generateRefreshToken(userContext.getUsername());
        log.debug("为用户 {} 生成刷新令牌成功", userContext.getUsername());
        return token;
    }

    /**
     * 生成令牌对(访问令牌 + 刷新令牌)
     *
     * @param userContext 用户上下文
     * @return 令牌对
     */
    public TokenPair generateTokenPair(UserContext userContext) {
        String accessToken = generateAccessToken(userContext);
        String refreshToken = generateRefreshToken(userContext);
        
        return new TokenPair(accessToken, refreshToken);
    }

    /**
     * 使用用户基本信息生成访问令牌
     *
     * @param userId      用户ID
     * @param username    用户名
     * @param nickname    昵称
     * @param tenantId    租户ID
     * @param roles       角色列表
     * @param permissions 权限列表
     * @return 访问令牌
     */
    public String generateAccessToken(Long userId, String username, String nickname, 
                                      Long tenantId, List<String> roles, List<String> permissions) {
        UserContext userContext = UserContext.builder()
                .userId(userId)
                .username(username)
                .nickname(nickname)
                .tenantId(tenantId)
                .roles(roles)
                .permissions(permissions)
                .build();
        
        return generateAccessToken(userContext);
    }

    /**
     * 使用刷新令牌重新生成访问令牌
     *
     * @param refreshToken 刷新令牌
     * @param userContext  用户上下文(包含最新的用户信息)
     * @return 新的访问令牌
     */
    public String refreshAccessToken(String refreshToken, UserContext userContext) {
        // 验证刷新令牌
        if (!jwtService.validateToken(refreshToken) || !jwtService.isRefreshToken(refreshToken)) {
            throw new IllegalArgumentException("无效的刷新令牌");
        }

        // 检查刷新令牌的主体是否与用户一致
        String tokenSubject = jwtService.getSubject(refreshToken);
        if (!userContext.getUsername().equals(tokenSubject)) {
            throw new IllegalArgumentException("刷新令牌与用户不匹配");
        }

        return generateAccessToken(userContext);
    }

    /**
     * 令牌对
     */
    public static class TokenPair {
        private final String accessToken;
        private final String refreshToken;

        public TokenPair(String accessToken, String refreshToken) {
            this.accessToken = accessToken;
            this.refreshToken = refreshToken;
        }

        public String getAccessToken() {
            return accessToken;
        }

        public String getRefreshToken() {
            return refreshToken;
        }

        @Override
        public String toString() {
            return "TokenPair{" +
                    "accessToken='" + accessToken + '\'' +
                    ", refreshToken='" + refreshToken + '\'' +
                    '}';
        }
    }
}
